home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / amiga / gcctls92.lha / ar / replace.c < prev   
C/C++ Source or Header  |  1992-04-20  |  6KB  |  184 lines

  1. /*-
  2.  * Copyright (c) 1990 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Hugh Smith at The University of Guelph.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36.  
  37. #ifndef lint
  38. static char sccsid[] = "@(#)replace.c    5.8 (Berkeley) 3/15/91";
  39. #endif /* not lint */
  40.  
  41. #include <sys/param.h>
  42. #include <sys/stat.h>
  43. #include <fcntl.h>
  44. #include <dirent.h>
  45. #include <errno.h>
  46. #include <unistd.h>
  47. #include <ar.h>
  48. #include <stdio.h>
  49. #include <string.h>
  50. #include "archive.h"
  51. #include "extern.h"
  52.  
  53. extern CHDR chdr;            /* converted header */
  54. extern char *archive;            /* archive name */
  55. extern char *tname;                     /* temporary file "name" */
  56.  
  57. /*
  58.  * replace --
  59.  *    Replace or add named members to archive.  Entries already in the
  60.  *    archive are swapped in place.  Others are added before or after 
  61.  *    the key entry, based on the a, b and i options.  If the u option
  62.  *    is specified, modification dates select for replacement.
  63.  */
  64. replace(argv)
  65.     char **argv;
  66. {
  67.     extern char *posarg, *posname;    /* positioning file name */
  68.     register char *file;
  69.     register int afd, curfd, mods, sfd;
  70.     struct stat sb;
  71.     CF cf;
  72.     off_t size, tsize;
  73.     int err, exists, tfd1, tfd2;
  74.     char *rname();
  75.  
  76.     err = 0;
  77.     /*
  78.      * If doesn't exist, simply append to the archive.  There's
  79.      * a race here, but it's pretty short, and not worth fixing.
  80.      */
  81.     exists = !stat(archive, &sb);
  82.     afd = open_archive(O_CREAT|O_RDWR);
  83.  
  84.     if (!exists) {
  85.         tfd1 = -1;
  86.         tfd2 = tmp();
  87.         goto append;
  88.     } 
  89.  
  90.     tfd1 = tmp();            /* Files before key file. */
  91.     tfd2 = tmp();            /* Files after key file. */
  92.  
  93.     /*
  94.      * Break archive into two parts -- entries before and after the key
  95.      * entry.  If positioning before the key, place the key at the
  96.      * beginning of the after key entries and if positioning after the
  97.      * key, place the key at the end of the before key entries.  Put it
  98.      * all back together at the end.
  99.      */
  100.     mods = (options & (AR_A|AR_B));
  101.     for (curfd = tfd1; get_arobj(afd);) {
  102.         if (*argv && (file = files(argv))) {
  103.             if ((sfd = open(file, O_RDONLY)) < 0) {
  104.                 err = 1;
  105.                 (void)fprintf(stderr, "ar: %s: %s.\n",
  106.                     file, strerror(errno));
  107.                 goto useold;
  108.             }
  109.             (void)fstat(sfd, &sb);
  110.             if (options & AR_U && sb.st_mtime <= chdr.date)
  111.                 goto useold;
  112.  
  113.             if (options & AR_V)
  114.                  (void)printf("r - %s\n", file);
  115.  
  116.             /* Read from disk, write to an archive; pad on write */
  117.             SETCF(sfd, file, curfd, tname, WPAD);
  118.             put_arobj(&cf, &sb);
  119.             (void)close(sfd);
  120.             skip_arobj(afd);
  121.             continue;
  122.         }
  123.  
  124.         if (mods && compare(posname)) {
  125.             mods = 0;
  126.             if (options & AR_B)
  127.                 curfd = tfd2;
  128.             /* Read and write to an archive; pad on both. */
  129.             SETCF(afd, archive, curfd, tname, RPAD|WPAD);
  130.             put_arobj(&cf, (struct stat *)NULL);
  131.             if (options & AR_A)
  132.                 curfd = tfd2;
  133.         } else {
  134.             /* Read and write to an archive; pad on both. */
  135. useold:            SETCF(afd, archive, curfd, tname, RPAD|WPAD);
  136.             put_arobj(&cf, (struct stat *)NULL);
  137.         }
  138.     }
  139.  
  140.     if (mods) {
  141.         (void)fprintf(stderr, "ar: %s: archive member not found.\n",
  142.             posarg);
  143.                 close_archive(afd);
  144.                 return(1);
  145.         }
  146.  
  147.     /* Append any left-over arguments to the end of the after file. */
  148. append:    while (file = *argv++) {
  149.         if (options & AR_V)
  150.             (void)printf("a - %s\n", file);
  151.         if ((sfd = open(file, O_RDONLY)) < 0) {
  152.             err = 1;
  153.             (void)fprintf(stderr, "ar: %s: %s.\n",
  154.                 file, strerror(errno));
  155.             continue;
  156.         }
  157.         (void)fstat(sfd, &sb);
  158.         /* Read from disk, write to an archive; pad on write. */
  159.         SETCF(sfd, file,
  160.             options & (AR_A|AR_B) ? tfd1 : tfd2, tname, WPAD);
  161.         put_arobj(&cf, &sb);
  162.         (void)close(sfd);
  163.     }
  164.     
  165.     (void)lseek(afd, (off_t)SARMAG, SEEK_SET);
  166.  
  167.     SETCF(tfd1, tname, afd, archive, NOPAD);
  168.     if (tfd1 != -1) {
  169.         tsize = size = lseek(tfd1, (off_t)0, SEEK_CUR);
  170.         (void)lseek(tfd1, (off_t)0, SEEK_SET);
  171.         copy_ar(&cf, size);
  172.     } else
  173.         tsize = 0;
  174.  
  175.     tsize += size = lseek(tfd2, (off_t)0, SEEK_CUR);
  176.     (void)lseek(tfd2, (off_t)0, SEEK_SET);
  177.     cf.rfd = tfd2;
  178.     copy_ar(&cf, size);
  179.  
  180.     (void)ftruncate(afd, tsize + SARMAG);
  181.     close_archive(afd);
  182.     return(err);
  183. }    
  184.